<template>
    <div class="vo-drag-position-item_list">
        <div
            ref="children"
            v-for="(child, index) in items"
            :key="index"
            class="handle_bar vo-drag-position-item"
            :class="{
                'select': isSelect(child)
            }"
            :style="itemStyle(child)"
            @click.stop.prevent="itemClick(child)"
        >
            <div class="vo-drag-position-item_content">
                <p class="vo-drag-position-item_coordinate">
                    <span>[{{child.width}}x{{child.height}}] - </span>
                    <span>[{{child.left}}x{{child.top}}]</span>
                </p>
                <template v-if="child.children">
                    <VoDragPositionMoveItems
                        :parent="child"
                        :canvasWidth="child.width"
                        :canvasHeight="child.height"
                        :items="child.children"
                        :currentItem="currentItem"
                        :operatorZIndex="operatorZIndex - 1"
                        @on-item-click="handleItemClick"
                        @on-fixed-position="sendFixedPosition"
                    ></VoDragPositionMoveItems>
                </template>
            </div>
            <div class="vo-drag-position-item_dragbar" :style="dragbarStyle" @mousedown.prevent.stop="handleMouseDown($event, child, index)">
                <svg width="18px" fill="currentColor" viewBox="0 0 24 24">
                    <path d="M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z"></path>
                    <path d="M0 0h24v24H0z" fill="none"></path>
                </svg>
            </div>
            <span class="vo-drag-position-item_resize" :style="resizeStyle" @mousedown.prevent.stop="handleResizeMouseDown($event, child)"></span>
        </div>
    </div>
</template>

<script>
export default {
    name: 'VoDragPositionMoveItems',
    props: {
        items: {
            type: Array,
            default: () => []
        },
        parent: Object,
        // 当前选中
        currentItem: Object,
        // 画布宽度
        canvasWidth: Number,
        // 画布高度
        canvasHeight: Number,
        // 操作符层级
        operatorZIndex: {
            type: Number,
            default: 999
        }
    },
    data() {
        return {
            minSize: 40,
            moveing: false,
            sizeing: false,
            draping: false,
            originalEvent: {
                offsetX: 0,
                offsetY: 0
            }
        }
    },
    computed: {
        dragbarStyle() {
            return {
                zIndex: this.operatorZIndex - 1
            }
        },
        resizeStyle() {
            return {
                zIndex: this.operatorZIndex - 1
            }
        }
    },
    methods: {
        // item样式
        itemStyle(item) {
            if (!item) return null;
            const { width = 0, height = 0, top = 0, left = 0 } = item;
            return {
                width: `${width}px`,
                height: `${height}px`,
                top: `${top}px`,
                left: `${left}px`
            }
        },
        // item是否选中
        isSelect(item) {
            return item === this.currentItem
        },
        // item点击
        itemClick(item) {
            this.$emit('on-item-click', item)
            this.sendFixedPosition({ left: item.left, top: item.top })
        },
        handleItemClick(item) {
            this.$emit('on-item-click', item)
        },
        // 更新辅助线
        sendFixedPosition(item) {
            this.$emit('on-fixed-position', {
                top: this.parent ? item.top + this.parent.top : item.top,
                left: this.parent ? item.left + this.parent.left : item.left
            })
        },
        // item移动
        handleMouseDown(e, item, index) {
            document.onmousemove = null;
            document.onmouseup = null;
            // 获取目标元素
            const odiv = this.$refs.children[index];
            odiv.classList.add('active')
            // 算出鼠标相对元素的位置
            const disX = e.clientX - odiv.offsetLeft;
            const disY = e.clientY - odiv.offsetTop;
            const disW = odiv.offsetWidth;
            const disH = odiv.offsetHeight;
            // 是否可超出父级的限制(约束子集是否可超出子集的范围)
            let overstep = false;
            if (this.parent) {
                overstep = this.parent.overstep
            }

            this.moveing = true;
            this.sendFixedPosition({ left: item.left, top: item.top })

            // 鼠标按下并移动的事件
            document.onmousemove = (e) => {
                // 用鼠标的位置减去鼠标相对元素的位置，得到元素的位置
                let left = e.clientX - disX;
                let top = e.clientY - disY;
                if (!overstep && this.canvasWidth) {
                    left = Math.min(Math.max(left, 0), this.canvasWidth - disW)
                }
                if (!overstep && this.canvasHeight) {
                    top = Math.min(Math.max(top, 0), this.canvasHeight - disH)
                }
                item.left = left;
                item.top = top;
                this.sendFixedPosition({ left: item.left, top: item.top })
            };
            document.onmouseup = (e) => {
                this.moveing = false;
                odiv.classList.remove('active')
                document.onmousemove = null;
                document.onmouseup = null;
            };
        },
        // item大小改变
        handleResizeMouseDown(e, item) {
            document.onmousemove = null;
            document.onmouseup = null;
            // 算出鼠标相对元素的位置
            const cX = e.clientX;
            const cY = e.clientY;
            const width = item.width;
            const height = item.height;
            const { overstep = false, minResizeWidth = 0, minResizeHeight = 0, maxResizeWidth = 0, maxResizeHeight = 0 } = item;
            // const parentOverstep = overstep;
            let parentOverstep = false;
            if (this.parent) {
                parentOverstep = this.parent.overstep
            }

            this.sizeing = true;

            // 鼠标按下并移动的事件
            document.onmousemove = (e) => {
                // 用鼠标的位置减去鼠标相对元素的位置，得到元素的位置
                const w = e.clientX - cX;
                const h = e.clientY - cY;
                let rWidth = width + w;
                let rHeight = height + h;

                /**
                 * 限制最小值 - start
                 * */
                if (minResizeWidth) {
                    rWidth = Math.max(rWidth, minResizeWidth)
                }
                // 若限制了不能超出父级(overstep === false)，限制小于子元素中最大的位置坐标
                if (!overstep && item.children && item.children.length) {
                    const widthList = item.children.map(e => e.left + e.width)
                    const maxWidth = Math.max(...widthList)
                    if (rWidth < maxWidth) {
                        rWidth = maxWidth
                    }
                }
                if (minResizeHeight) {
                    rHeight = Math.max(rHeight, minResizeHeight)
                }
                if (!overstep && item.children && item.children.length) {
                    const heightList = item.children.map(e => e.top + e.height)
                    const maxHeight = Math.max(...heightList)
                    if (rHeight < maxHeight) {
                        rHeight = maxHeight
                    }
                }
                /**
                 * 限制最小值 - end
                 * */

                /**
                 * 限制最大值 - start
                 * */
                if (maxResizeWidth) {
                    rWidth = Math.min(rWidth, maxResizeWidth)
                }
                // 限制宽度超出边界线
                if (!parentOverstep && rWidth + item.left > this.canvasWidth) {
                    rWidth = Math.max(0, this.canvasWidth - item.left)
                }
                if (maxResizeHeight) {
                    rHeight = Math.min(rHeight, maxResizeHeight)
                }
                // 限制高度超出边界线
                if (!parentOverstep && rHeight + item.top > this.canvasHeight) {
                    rHeight = Math.max(0, this.canvasHeight - item.top)
                }
                /**
                 * 限制最大值 - end
                 * */
                item.width = Math.max(this.minSize, rWidth);
                item.height = Math.max(this.minSize, rHeight);
            };
            document.onmouseup = (e) => {
                this.sizeing = false;
                document.onmousemove = null;
                document.onmouseup = null;
            };
        },
    }
}
</script>

<style lang="scss" scoped>
.vo-drag-position-item_list{
    position: absolute;
    width: 100%;
    height: 100%;
    box-sizing: border-box;
}
.vo-drag-position-item{
    position: absolute;
    left: 0;
    top: 0;
    display: inline-block;
    box-sizing: border-box;
    background: #fff;
    // overflow: hidden;
    z-index: 1;
    transition: box-shadow 200ms cubic-bezier(0, 0, 0.2, 1);
    box-shadow: 0px 0px 4px 1px #ccc;

    &.select{
        z-index: 2;
        box-shadow: 0px 0px 4px 2px #409eff;
        & > .vo-drag-position-item_dragbar{
            display: inline-block;
        }
        & > .vo-drag-position-item_resize{
            display: inline-block;
        }
    }
    &.active{
        z-index: 2;
        box-shadow: 0px 0px 4px 2px #E6A23C;
    }
    .vo-drag-position-item_content{
        position: relative;
        height: 100%;
        border-radius: 4px;
        // background: url('~@/assets/img/img2.jpeg');
        background-size: 100% 100%;
        background-repeat: no-repeat;
    }
    .vo-drag-position-item_coordinate{
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        text-align: right;
    }
    .vo-drag-position-item_dragbar{
        display: none;
        position: absolute;
        top: 0;
        left: 0;
        cursor: move;
    }
    .vo-drag-position-item_resize{
        position: absolute;
        bottom: 0;
        right: 0;
        display: none;
        width: 10px;
        height: 10px;
        background: #fff;
        border: solid 1px #ccc;
        background: #fff;
        cursor: nw-resize;
    }
}
</style>
